//==========================================================================
// Copyright (c) 2000-2006,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <ddk.h>
#include <bulverde.h>
#include <drvpub.h>
#include "display_def.h"

#define SPI_SCLK    36
#define SPI_TXD     13
#define SPI_FRM     14
#define SPI_RXD     11

#define LCD_nRESET  24
#define LCD_RS      77

static void SPI2Init(void)
{
    #define CKEN3_SSP2      (1 << 3)    /* SSP2 Unit Clock Enable */
    CKEN |= CKEN3_SSP2;

    Gpio_SetDir(SPI_SCLK, GPIO_PIN_OUT);
    Gpio_SetAFR(SPI_SCLK, GPIO_AS_AF2);
    //set spi_txd
    Gpio_SetDir(SPI_TXD, GPIO_PIN_OUT);
    Gpio_SetAFR(SPI_TXD, GPIO_AS_AF1);
    //set spi_frm  SPI_CS -- must be GPIO only because of the polarity of CS -- must be high for PMIC active
    Gpio_SetDir(SPI_FRM, GPIO_PIN_OUT);
    Gpio_SetAFR(SPI_FRM, GPIO_AS_GPIO);


    SSCR0_2 = (unsigned long)0x00d00407;//Samsung spi 24bits

    SSCR1_2 = (unsigned long)0x100007D8;

    SSCR0_2 |= SSCR0_SSE;

}

void LcdHWSetup(void)
{
    int gpio_x;

    for( gpio_x = 58; gpio_x <= 76 ; gpio_x++ )
    {
            Gpio_SetDir( gpio_x, GPIO_PIN_OUT );
            Gpio_SetOutLow(gpio_x);
            Gpio_SetAFR( gpio_x, GPIO_AS_AF2 );
    }

    Gpio_SetDir( 77, GPIO_PIN_OUT );
    Gpio_SetAFR( 77, GPIO_AS_AF2 );

    Gpio_SetDir( 86, GPIO_PIN_OUT );
    Gpio_SetOutLow(86);
    Gpio_SetAFR( 86, GPIO_AS_AF2 );

    Gpio_SetDir( 87, GPIO_PIN_OUT );
    Gpio_SetOutLow(87);
    Gpio_SetAFR( 87, GPIO_AS_AF2 );
}

static void LcdReset(void)
{
    Gpio_SetDir(LCD_nRESET, GPIO_PIN_OUT);
    Gpio_SetAFR(LCD_nRESET, GPIO_AS_GPIO);

    Gpio_SetOutHigh(LCD_nRESET);

    DzDelay(20 * 1000);

    Gpio_SetOutLow(LCD_nRESET);

    DzDelay(20 * 1000);

    Gpio_SetOutHigh(LCD_nRESET);


}

void SPIWrite(unsigned long data)
{

    SSCR0_2 |= SSCR0_SSE;

    Gpio_SetOutLow(SPI_FRM);

    SSDR_2 = data;

    SSCR0_2 |= SSCR0_SSE;

    TIMEOUT_INIT(3*1000);
    while( (SSSR_2 & SSSR_BSY) && !TIMEOUT_FOUNDED() ) { };

    Drv_Assert(!TIMEOUT_FOUNDED() && "SPIWrite Fail\n");

    Gpio_SetOutHigh(SPI_FRM);
}

void LcdWriteIndx(unsigned long data)
{
    data |= (0x70 << 16);
    SPIWrite(data);
}

void LcdWriteData(unsigned long data)
{
    data |= (0x72 << 16);
    SPIWrite(data);
}

void LcdSamsungInit(void)
{
    //Start the oscillation circuit
    LcdWriteIndx(0x0000);
    LcdWriteData(0x0001);

    DzDelay(10*1000);

    //Display off
    LcdWriteIndx(0x0007);
    LcdWriteData(0x0004);

    //VCL1 setting
    LcdWriteIndx(0x0011);//Power control 2
    LcdWriteData(0x3f04);

    //1'VcomH setting;  2'Amplitude of VCOM setting
    LcdWriteIndx(0x0014);//Power control 5
    LcdWriteData(0x2420);

    //POWER CONTROL 1 setting
    LcdWriteIndx(0x0010);
    LcdWriteData(0x1b00);

    //POWER CONTROL 4 setting
    LcdWriteIndx(0x0013);
    LcdWriteData(0x0040);

    //POWER CONTROL 4 setting
    LcdWriteIndx(0x0013);
    LcdWriteData(0x0060);

    //POWER CONTROL 4 setting
    LcdWriteIndx(0x0013);
    LcdWriteData(0x0070);

    //Specifies 262k-color mode
    LcdWriteIndx(0x0001);//Driver output control
    LcdWriteData(0x1927);

    //The line inversion waveform is set
    LcdWriteIndx(0x0002);//LCD-Driving-Waveform Control
    LcdWriteData(0x0700);

    //262k-color mode
    LcdWriteIndx(0x0003);//Entry Mode
    LcdWriteData(0x1030);

    //Front/Back Porch setting
    LcdWriteIndx(0x0008);//Display control 2
    LcdWriteData(0x020e);//0x0808

    //External clock setting
    LcdWriteIndx(0x000b);//Frame Cycle Control
    LcdWriteData(0x0620);

    //18-bit RGB interface setting
    LcdWriteIndx(0x000c);//External Display Interface
    LcdWriteData(0x0110);

    //Gage Out operation
    LcdWriteIndx(0x0007);//Display control
    LcdWriteData(0x0015);

    //Source output Normal Display
    LcdWriteIndx(0x0007);//Display control
    LcdWriteData(0x0017);

    //RAM Address Set
    LcdWriteIndx(0x0020);//
    LcdWriteData(0x0000);

    //RAM Address Set
    LcdWriteIndx(0x0021);//
    LcdWriteData(0x0000);

    //Gamma setting
    LcdWriteIndx(0x0030);
    LcdWriteData(0x0000);

    LcdWriteIndx(0x0031);
    LcdWriteData(0x0000);

    LcdWriteIndx(0x0032);
    LcdWriteData(0x0000);

    LcdWriteIndx(0x0033);
    LcdWriteData(0x0000);

    LcdWriteIndx(0x0034);
    LcdWriteData(0x4440);

    LcdWriteIndx(0x0035);
    LcdWriteData(0x0110);

    LcdWriteIndx(0x0036);
    LcdWriteData(0x0014);

    LcdWriteIndx(0x0037);
    LcdWriteData(0x1f0e);

    LcdWriteIndx(0x0038);
    LcdWriteData(0x0000);

    LcdWriteIndx(0x0039);
    LcdWriteData(0x0000);

    //Write Data to GRAM
    LcdWriteIndx(0x0022);
    //LcdWriteData(0x0000);

}

void LcdSamsung_PowerOff()
{
    //
    LcdWriteIndx(0x000b);//Frame cycle control
    LcdWriteData(0x0000);

    //
    LcdWriteIndx(0x0007);//Display control
    LcdWriteData(0x0016);

    //
    LcdWriteIndx(0x0007);//
    LcdWriteData(0x0000);

    //
    LcdWriteIndx(0x0010);//Power control 1
    LcdWriteData(0x0000);

    //
    LcdWriteIndx(0x0013);//Power control 4
    LcdWriteData(0x0060);

    //
    LcdWriteIndx(0x0013);//
    LcdWriteData(0x0040);

    //
    LcdWriteIndx(0x0013);//
    LcdWriteData(0x0000);

}

#if 0

#define Lcd_WriteIndx1 LcdWriteIndx
#define Lcd_WriteData1 LcdWriteData
#define lcd_delay DzDelay
#define CONFIG_YUHUATEL_NE2

void LCD_Module_Init(void)
{
	/*Frame cycle control*/
	Lcd_WriteIndx1(0x0b);
	Lcd_WriteData1(0x0620);

	/*External interface control*/
	Lcd_WriteIndx1(0x0c);
	Lcd_WriteData1(0x0110);



	/*Power control 2*/
#if 1
	Lcd_WriteIndx1(0x11);
	Lcd_WriteData1(0x3303);//0x2903
	/*Power control 4*/
	Lcd_WriteIndx1(0x14);
	Lcd_WriteData1(0x8918);//0x071e 0x8910
	/*Power control 1*/
	Lcd_WriteIndx1(0x10);
	Lcd_WriteData1(0x3c00);//0x1d20
	/*Power control 3*/
	Lcd_WriteIndx1(0x13);
	Lcd_WriteData1(0x0040);//0x0040
	lcd_delay(10*1000);
#endif

#if 0
	Lcd_WriteIndx1(0x11);
	Lcd_WriteData1(0x2903);
	/*Power control 4*/
	Lcd_WriteIndx1(0x14);
	Lcd_WriteData1(0x071e);
	/*Power control 1*/
	Lcd_WriteIndx1(0x10);
	Lcd_WriteData1(0x1d20);
	/*Power control 3*/
	Lcd_WriteIndx1(0x13);
	Lcd_WriteData1(0x0040);
	lcd_delay(10*1000);
#endif
	/*Power control 3*/
	Lcd_WriteIndx1(0x13);
	Lcd_WriteData1(0x0060);
	lcd_delay(50*1000);

	/*Power control 3*/
	Lcd_WriteIndx1(0x13);
	Lcd_WriteData1(0x0070);
	lcd_delay(40*1000);

	/*Driver output control
	14->VSPL:0
	13->HSPL:0
	12->DPL	:0
	11->EPL	:0
	10->SM	:0
	9->GS	:0
	8->SS	:0
	*/

#if defined(CONFIG_YUHUATEL_OMEGA) || defined(CONFIG_YUHUATEL_RUDYS) || defined(CONFIG_YUHUATEL_BALLY_V1T1)
	Lcd_WriteIndx1(0x01);
	Lcd_WriteData1(0x0027);
	/*Driving waveform control*/
	Lcd_WriteIndx1(0x02);
	Lcd_WriteData1(0x0700);
	/*Entry mode*/
	Lcd_WriteIndx1(0x03);
	Lcd_WriteData1(0x1020);
	/*Ram address */
	Lcd_WriteIndx1(0x20);
	Lcd_WriteData1(0x00ef);
	Lcd_WriteIndx1(0x21);
	Lcd_WriteData1(0x0000);
#elif defined(CONFIG_YUHUATEL_NE2)
	Lcd_WriteIndx1(0x01);
	Lcd_WriteData1(0x00227);
	/*Driving waveform control*/
	Lcd_WriteIndx1(0x02);
	Lcd_WriteData1(0x0700);
	/*Entry mode*/
	Lcd_WriteIndx1(0x03);
	Lcd_WriteData1(0x1030);
	/*Ram address */
	Lcd_WriteIndx1(0x20);
	Lcd_WriteData1(0x0000);
	Lcd_WriteIndx1(0x21);
	Lcd_WriteData1(0x0000);
#endif

	/*Display control*/
	Lcd_WriteIndx1(0x07);
	Lcd_WriteData1(0x0000);
	/*Blank period control 1*/
	Lcd_WriteIndx1(0x08);
	Lcd_WriteData1(0x020e);

	/*Gate scan position*/
	Lcd_WriteIndx1(0x40);
	Lcd_WriteData1(0x0000);
	/*1st screen*/
	Lcd_WriteIndx1(0x42);
	Lcd_WriteData1(0x013f);
	Lcd_WriteIndx1(0x43);
	Lcd_WriteData1(0x0000);

	/*2nd screen*/
	Lcd_WriteIndx1(0x44);
	Lcd_WriteData1(0x0000);
	Lcd_WriteIndx1(0x45);
	Lcd_WriteData1(0x0000);

	/*Horizontal address*/
	Lcd_WriteIndx1(0x46);
	Lcd_WriteData1(0xef00);

	/*Vertical address*/
	Lcd_WriteIndx1(0x47);
	Lcd_WriteData1(0x013f);
	Lcd_WriteIndx1(0x48);
	Lcd_WriteData1(0x0000);

	/*Gamma control*/
	Lcd_WriteIndx1(0x30);
	Lcd_WriteData1(0x0);//0x0707
	Lcd_WriteIndx1(0x31);
	Lcd_WriteData1(0x0707);
	Lcd_WriteIndx1(0x32);
	Lcd_WriteData1(0x0006);//0x0707
	Lcd_WriteIndx1(0x33);
	Lcd_WriteData1(0x0403);//0x0707
	Lcd_WriteIndx1(0x34);
	Lcd_WriteData1(0x0107);//0x0707
	Lcd_WriteIndx1(0x35);
	Lcd_WriteData1(0x0101);//0x0707
	Lcd_WriteIndx1(0x36);
	Lcd_WriteData1(0x0707);
	Lcd_WriteIndx1(0x37);
	Lcd_WriteData1(0x0304);//0x0707
	Lcd_WriteIndx1(0x38);
	Lcd_WriteData1(0x0a0a);
	Lcd_WriteIndx1(0x39);
	Lcd_WriteData1(0x0706);

	/*Display control*/
	Lcd_WriteIndx1(0x07);
	Lcd_WriteData1(0x0011);
	lcd_delay(100*1000);


	/*Display control*/
	Lcd_WriteIndx1(0x07);
	Lcd_WriteData1(0x0017);

	/*External interface control*/
	Lcd_WriteIndx1(0x0c);
	Lcd_WriteData1(0x0110);

	/*Write to GRAM*/
	Lcd_WriteIndx1(0x22);
	Lcd_WriteData1(0x0010);


}
#endif
///////////////////////////////////////////////////////////////////////////////

void Lcm_SetupGPIOs(DisplayContext *pCxt)
{
    // 16bpp support
    // bits 58-77
    GPDR1 |= (0x3f << 26);
    GPDR2 |= 0x00003fff;

    GAFR1_U = (GAFR1_U & ~(0xfff << 20)) | (0xaaa << 20);
    GAFR2_L = (GAFR2_L & 0xf0000000) | 0x0aaaaaaa;
}

void Lcm_DisplayOn(DisplayContext *pCxt, int LcmPowerOn)
{
    if(LcmPowerOn) {
        SPI2Init();
        LcdHWSetup();
        LcdReset();
        DzDelay(20 * 1000);
        LcdSamsungInit();
    }
    else {
        LcdSamsungInit();
        DzDelay(150*1000);
    }
}

void Lcm_DisplayOff(DisplayContext *pCxt)
{
#if 1
    LcdSamsung_PowerOff();
    DzDelay(60 * 1000);
#endif
}
